﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.UI.WebControls;
using System.Windows.Forms;
using PMC;
using PMC.Interfaces;
using PMC.Plugins;
using PMC.Structs;
using PMC.Urls;

namespace PMCgui
{
    public partial class ProgressControl : TransitionUserControl
    {
        private static ProgressControl instance;

        public static ProgressControl Instance
        {
            get { return instance ?? (instance = new ProgressControl()); }
        }

        public static bool HasInstance
        {
            get
            {
                return instance == null;                
            }
        }

        private CookieContainer cookieJar;
        private readonly static string informationFormat = Language.Instance.EstimatedTimeLeft + Environment.NewLine + Language.Instance.LinksLeft;

        private ProgressControl()
        {
            InitializeComponent();
            Dock = DockStyle.Fill;         

            Log.Instance.LogMessageReceived += OnLogMessageReceived;
            //UriCollector.UriCollectorChanged += UriCollector_UriCollectorChanged;
            SubscribeCollector();
        }

        private void OnLogMessageReceived(Log.LogEventArgs args)
        {
            var newLogMessage = args.Message;
            Color color = Global.LogMessage;
            switch (newLogMessage.Type)
            {
                case LogType.Warning:
                    color = Global.LogWarning;
                    break;
                case LogType.Error:
                    color = Global.LogError;
                    break;

            }
            var listItem = new ListViewItem(new[] { newLogMessage.Date.ToString(), newLogMessage.Message }) { BackColor = color };
            if (IsHandleCreated)
                Invoke((MethodInvoker)delegate() { lbLog.BeginUpdate(); lbLog.Items.Add(listItem); listItem.EnsureVisible(); lbLog.EndUpdate(); });
        }

        //void UriCollector_UriCollectorChanged(object sender, EventArgs e)
        //{
        //    SubscribeCollector();
        //}

        /// <summary>
        /// Subscribes to new uricollector
        /// </summary>
        private void SubscribeCollector()
        {
            HandleCreated += ProgressControl_HandleCreated;
            HandleDestroyed += ProgressControl_HandleDestroyed;
        }

        #region Url Collector Events
        void ProgressControl_HandleDestroyed(object sender, EventArgs e)
        {
            UriCollector.UrlAdded -= ActiveCollector_Url_Added;
            UriCollector.UrlDeleted -= ActiveCollector_UrlDeleted;
            UriCollector.Completed -= ActiveCollector_Completed;
            UriCollector.Error -= ActiveCollector_Error;
        }

        void ProgressControl_HandleCreated(object sender, EventArgs e)
        {
            UriCollector.UrlAdded += ActiveCollector_Url_Added;
            UriCollector.UrlDeleted += ActiveCollector_UrlDeleted;
            UriCollector.Completed += ActiveCollector_Completed;
            UriCollector.Error += ActiveCollector_Error;
        }

        void ActiveCollector_Error(object sender, System.IO.ErrorEventArgs e)
        {
            Exception error = e.GetException();
            MessageBox.Show(Language.Instance.ErrorFetchingEmails + Environment.NewLine + error.Message + Environment.NewLine + error.InnerException);
            ActiveCollector_Completed(sender, e);
        }

        void ActiveCollector_Completed(object sender, EventArgs e)
        {
            Invoke((MethodInvoker)delegate { btUpdate.Enabled = true; });
        }

        void ActiveCollector_UrlDeleted(object sender, UrlEventArgs e)
        {
            Invoke((MethodInvoker)delegate { UpdateUrls(e.Url, false); });
        }

        void ActiveCollector_Url_Added(object sender, UrlEventArgs e)
        {
            Invoke((MethodInvoker)delegate { UpdateUrls(e.Url, true); });
        } 
        #endregion

        private void UpdateUrls(Uri change, bool add)
        {
            if (IsHandleCreated)
            {
                lbUrls.BeginUpdate();
                if (add)
                {
                    lbUrls.Items.Add(change);
                }
                else
                {
                    for (int i = lbUrls.Items.IndexOf(change); i >= 0; i--)
                    {
                        lbUrls.Items.RemoveAt(i);
                    }
                }
                lbUrls.EndUpdate();
                UpdateLinks();
            }
        }

        private void UpdateLinks()
        {
            double time = lbUrls.Items.Count * Website.Websites.Average(c => c.Interval) / pnlBrowsers.Controls.Count;
            if (double.IsInfinity(time) || double.IsNaN(time)) return;
            var left = TimeSpan.FromMilliseconds(time);
            lbInformation.Text = String.Format(informationFormat, left, lbUrls.Items.Count);
        }

        public WebbrowserControl AddBrowser(IWbrowser w)
        {
            var v = new WebbrowserControl(w);
            pnlBrowsers.Controls.Add(v);
            return v;
        }

        private void btUpdate_Click(object sender, EventArgs e)
        {
            btUpdate.Enabled = false;
            UriCollector.ActiveCollector.UpdateAsync()
                .ContinueWith(resultTask =>
                {
                    btUpdate.Enabled = true;
                    if (resultTask.IsFaulted)
                    {
                        MessageBox.Show(Language.Instance.UrlCollectionActive);
                    }
                }, default(CancellationToken),
                TaskContinuationOptions.None,
                TaskScheduler.FromCurrentSynchronizationContext());
        }

        private void btAddBrowser_Click(object sender, EventArgs e)
        {
            AddBrowser(new WbrowserWebRequest());
        }

        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            lbUrls.BeginUpdate();
            foreach (Uri item in lbUrls.SelectedItems.Cast<Uri>().ToList())
            {
                UriCollector.ActiveCollector.Remove(item);
            }
            lbUrls.EndUpdate();
        }

        private void addToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string value = null;
            using (var prompt = new PromptForm())
            {
                prompt.ShowDialog();
                value = prompt.Input;
            }

            if (!string.IsNullOrWhiteSpace(value))
            {
                Uri uri;

                if (Uri.TryCreate(value, UriKind.Absolute, out uri))
                {
                    UriCollector.ActiveCollector.Add(uri);
                }
                else
                {
                    MessageBox.Show(Language.Instance.UrlNotWellformed, Language.Instance.Url, MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }
        }

        public static new void Dispose()
        {
            instance = null;
        }
    }
}
